ECON 494 - Spatial Data Science Project
Our project aimed to analyze the Ukraine conflict using spatial
analysis and maps generated through data from ACLED (Armed Conflict
Location & Event Data Project). Focusing on the violence targeting
civilians after invasion of Russia into Ukraine, we utilized R
programming to extract and visualize the conflict data, enabling us to
present a comprehensive overview of the events and their spatial
distribution.
library(sp)
library(raster)
library(ggplot2)
library(dplyr)
Attaching package: ‘dplyr’
The following objects are masked from ‘package:raster’:
intersect, select, union
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
library(tidyverse)
── Attaching core tidyverse packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ forcats 1.0.0 ✔ stringr 1.5.0
✔ lubridate 1.9.2 ✔ tibble 3.2.1
✔ purrr 1.0.1 ✔ tidyr 1.3.0
✔ readr 2.1.4 ── Conflicts ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ tidyr::extract() masks raster::extract()
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
✖ dplyr::select() masks raster::select()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
library(conflicted)
Introduction
Russia invaded Ukraine in February 2022, resulting in the highest
levels of political violence recorded in a single country by
ACLED.
Civilians in Ukraine have faced shelling, indiscriminate strikes,
deliberate attacks, and harsh treatment in occupied areas.
Russian forces targeted Kyiv but retreated in northern Ukraine
while quickly seizing territories in southern and eastern
regions.
Over 5,000 reported civilian fatalities have occurred, but the
actual toll is likely much higher.
Different regions of Ukraine experienced varying levels of
violence and occupation during the conflict.
#ukraine_states_rds <- raster::getData('GADM', country = "UKR", level = 1)
ukraine_states_rds = readRDS("ukraine.rds") #https://gadm.org/download_country.html
ukraine_map <- ggplot() +
geom_polygon(data=ukraine_states_rds, aes(x = long, y = lat, group = group, fill = id), fill="orange", alpha = 0.6 ) + guides(fill = "none")
Regions defined for each Polygons
ukraine_map

east_ukraine_states_rds_names <- list("Dnipropetrovs'k", "Donets'k", "Luhans'k" , "Kharkiv", "Zaporizhzhya")
east_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% east_ukraine_states_rds_names)
south_ukraine_states_rds_names <- list("Chernihiv", "Kiev", "Kiev City", "Zhytomyr", "Sumy")
south_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% south_ukraine_states_rds_names)
central_ukraine_states_rds_names <- list("Cherkasy", "Kirovohrad", "Poltava", "Vinnytsya")
central_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% central_ukraine_states_rds_names)
western_ukraine_states_rds_names <- list("Volyn", "Chernivtsi", "Ivano-Frankivs'k", "Khmel'nyts'kyy", "Rivne", "L'viv", "Ternopil'", "Transcarpathia")
western_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% western_ukraine_states_rds_names)
southern_ukraine_states_rds_names <- list("Crimea", "Kherson", "Mykolayiv", "Odessa")
southern_ukraine_states_rds <- subset(ukraine_states_rds, NAME_1 %in% southern_ukraine_states_rds_names)
ukraine_map2 <- ukraine_map +
geom_polygon(data=east_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="red", alpha=0.2, color="black") +
geom_polygon(data=south_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="black", alpha=0.2, color="black") +
geom_polygon(data=central_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="darkblue", alpha=0.4, color="black") +
geom_polygon(data=western_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="lightblue", alpha=0.2, color="black") +
geom_polygon(data=southern_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black")
Regions defined for each PolygonsRegions defined for each PolygonsRegions defined for each PolygonsRegions defined for each PolygonsRegions defined for each Polygons
ukraine_map2

centroid <- ukraine_states_rds$centroid <- coordinates(ukraine_states_rds)
ukraine_states_rds_names <- ukraine_states_rds$NAME_1
ukraine_map3 <- ukraine_map2 +
geom_text(aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds_names), size=2) + labs(title = "Regions of Ukraine", fontface="bold") + theme_void() + theme(plot.title = element_text(hjust = 0.5, face = "bold")) + coord_map(projection = "albers", lat0 = 49, lat1 = 54)
ukraine_map3

Conflict Data (ACLED)
eastern_ukraine_states_names = list("Dnipropetrovsk", "Luhansk", "Donetsk", "Kharkiv", "Zaporizhia")
conflict <- read_csv('ukraine.csv', show_col_types = FALSE)
conflict$event_date <- as.Date(conflict$event_date, format = "%d %B %Y")
unique(conflict$admin1)
[1] "Dnipropetrovsk" "Luhansk" "Donetsk" "Kharkiv" "Kherson" "Sumy" "Zaporizhia" "Kyiv City" "Chernihiv"
[10] "Crimea" "Chernivtsi" "Ivano-Frankivsk" "Khmelnytskyi" "Lviv" "Mykolaiv" "Odesa" "Poltava" "Vinnytsia"
[19] "Kirovograd" "Zhytomyr" "Ternopil" "Cherkasy" "Kyiv" "Volyn" NA "Rivne" "Zakarpattia"
unique(conflict$event_type)
[1] "Explosions/Remote violence" "Battles" "Strategic developments" "Violence against civilians" "Protests"
[6] "Riots"
unique(conflict$sub_event_type)
[1] "Shelling/artillery/missile attack" "Armed clash" "Air/drone strike" "Remote explosive/landmine/IED"
[5] "Disrupted weapons use" "Other" "Agreement" "Attack"
[9] "Arrests" "Change to group/activity" "Looting/property destruction" "Non-state actor overtakes territory"
[13] "Abduction/forced disappearance" "Peaceful protest" "Protest with intervention" "Government regains territory"
[17] "Sexual violence" "Suicide bomb" "Grenade" "Non-violent transfer of territory"
[21] "Mob violence" "Excessive force against protesters" "Headquarters or base established" "Violent demonstration"
Apparent War Crimes in Northern Ukraine
Heavy Fighting Along the Frontline in Eastern Ukraine
Political Violence in Eastern Ukraine
Eastern Ukraine faces unprecedented violence, with three-quarters of
political violence events occurring in the region, primarily due to
shelling, artillery, and missile attacks. Despite relative distance from
the frontline, the Dnipropetrovsk region remains at risk, as Russia
continues air and missile strikes, exemplified by the deadly incident in
Dnipro on 14 January 2023.
conflict_eastern_ukraine <- conflict %>%
dplyr::filter(
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
admin1 %in% eastern_ukraine_states_names)
event_counts_eastern_ukraine <- conflict_eastern_ukraine %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), event_type)
east_ukraine_states_rds
class : SpatialPolygonsDataFrame
features : 5
extent : 32.96244, 40.21807, 46.07875, 50.46491 (xmin, xmax, ymin, ymax)
crs : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
variables : 10
Warning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NAWarning: no non-missing arguments, returning NA
names : GID_0, NAME_0, GID_1, NAME_1, VARNAME_1, NL_NAME_1, TYPE_1, ENGTYPE_1, CC_1, HASC_1
min values : UKR, Ukraine, UKR.15_1, Dnipropetrovs'k, Charkow|Jarkov|Karkov|Khar'kov, NA, Oblast', Region, NA, UA.DP
max values : UKR, Ukraine, UKR.8_1, Zaporizhzhya, Saporoshje|Zaporizhia|Zaporiz'ka Oblast'|Zaporojie|Zaporozhskaya Oblast'|Zaporozh'ye|Zaporožje, NA, Oblast', Region, NA, UA.ZP
eastern_ukraine_map <- ggplot() +
geom_polygon(data=east_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
eastern_ukraine_map

centroid <- east_ukraine_states_rds$centroid <- coordinates(east_ukraine_states_rds)
centroid[2] = centroid[2]+0.4
centroid[7] = centroid[7]-0.4
centroid[3] = centroid[3]-0.4
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = c("Dnipropetrovsk", "Donetsk", "Kharkiv", "Luhansk", "Zaporizhia")), color = "black", size = 4)
eastern_ukraine_map +
geom_point(data = event_counts_eastern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
geom_point(color="black", shape=21, data = event_counts_eastern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
scale_size_continuous(range = c(0.1, 5)) +
labs(color = "Event Type", size = "Number of Events") +
labs(title = "Political Violence in Eastern Ukraine", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5)) +
text

Conflict in Kharkiv
Although Russian forces were unable to break Ukrainian defenses
around the city of Kharkiv, they had occupied the bulk of the region’s
northern and eastern parts by April 2022, including Izium – a critical
transport hub Ukraine liberated almost the entire region in a surprise
counter-offensive in September 2022. Of over 800 events targeting
civilians, about three-quarters constituted artillery, missile, and
airstrike events, which also resulted in the majority of reported
civilian fatalities recorded in the region. About a third of these
occurred in March 2022 alone.
conflict_kharkiv <- conflict %>%
dplyr::filter(
civilian_targeting != "",
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
admin1 == "Kharkiv")
# Create a new column called 'new_event_type'
conflict_kharkiv$new_event_type <- NA
# Map values based on 'sub_event_type'
conflict_kharkiv$new_event_type[conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack")] <- conflict_kharkiv$sub_event_type[conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack")]
conflict_kharkiv$new_event_type[!(conflict_kharkiv$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Remote explosive/landmine/IED", "Attack"))] <- "Other violence"
number_of_events_kharkiv <- conflict_kharkiv %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), new_event_type)
kharkiv <- subset(ukraine_states_rds, NAME_1 == "Kharkiv")
kharkiv_map <- ggplot() +
geom_polygon(data=kharkiv, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
kharkiv_map

kharkiv_map +
geom_point(data = number_of_events_kharkiv, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
geom_point(color="black", shape=21, data = number_of_events_kharkiv, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Sub-Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Kharkiv", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Luhansk
The sheer scale of artillery, missile, and air attacks inflicted on
Luhansk region as well as intense close combat brought about immense
suffering for the civilians. On 11 March 2022, 56 elderly patients
reportedly died during the shelling of a nursing home in Kreminna, and
at least 60 people were killed in an airstrike on a school used as a
shelter in Bilohorivka on 7 May 2022. Over 50 civilians were also killed
during the shelling of Severodonetsk in March and May 2022. Following
the Russian occupation of the region in summer 2022, the number of
reports of civilians being targeted went sharply down; though the region
has remained highly kinetic, especially since autumn.
conflict_luhansk <- conflict %>%
dplyr::filter(
civilian_targeting != "",
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
admin1 == "Luhansk")
# Create a new column called 'new_event_type'
conflict_luhansk$new_event_type <- NA
# Map values based on 'sub_event_type'
conflict_luhansk$new_event_type[conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack")] <- conflict_luhansk$sub_event_type[conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack")]
conflict_luhansk$new_event_type[!(conflict_luhansk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Attack"))] <- "Other violence"
number_of_events_luhansk <- conflict_luhansk %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), new_event_type)
luhansk <- subset(ukraine_states_rds, NAME_1 == "Luhans'k")
luhansk_map <- ggplot() +
geom_polygon(data=luhansk, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
luhansk_map

luhansk_map +
geom_point(data = number_of_events_luhansk, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
geom_point(color="black", shape=21, data = number_of_events_luhansk, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Sub-Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Luhansk", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Donetsk
ACLED records over 16,000 events in Donetsk region, of which over
12,000 were attributed to shelling, artillery, missile, and airstrike
events. Only a small portion of these events – about 800 – could be
attributed to the direct targeting of civilian. The city of Mariupol was
the site of several mass casualty events ahead of the Russian
occupation. Mass casualty events due to long-range missile and artillery
strikes occurred in other parts of the region and on both sides of the
line of contact.
conflict_donetsk <- conflict %>%
dplyr::filter(
civilian_targeting != "",
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
admin1 == "Donetsk")
# Create a new column called 'new_event_type'
conflict_donetsk$new_event_type <- NA
# Map values based on 'sub_event_type'
conflict_donetsk$new_event_type[conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_donetsk$sub_event_type[conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_donetsk$new_event_type[!(conflict_donetsk$sub_event_type %in% c("Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_donetsk <- conflict_donetsk %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), new_event_type)
donetsk <- subset(ukraine_states_rds, NAME_1 == "Donets'k")
donetsk_map <- ggplot() +
geom_polygon(data=donetsk, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
donetsk_map

donetsk_map +
geom_point(data = number_of_events_donetsk, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
geom_point(color="black", shape=21, data = number_of_events_donetsk, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Sub-Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Donetsk", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Conflict in Zaporizhia
Russian forces occupied most of the Zaporizhia region in the first
weeks of the invasion, capturing the entire shore of the Sea of Azov,
including the Ukrainian navy base in Berdiansk, and an area stretching
between the Kherson and southern Donetsk regions up to the Dnipro river,
including the second-largest town of Melitopol. Ukrainian forces stopped
Russian forces in the area of Orikhiv and Huliaipole Although shelling
and air and drone strikes have accounted for about half of events
targeting civilians in the Zaporizhia region, civilians have also been
the subject of direct attacks. These include firing at vehicles carrying
evacuating civilians, as well as torture and execution. In areas under
Russian occupation, reports of the abduction of local officials,
teachers, journalists, Ukrainian army veterans, and civil activists are
common.
conflict_zaporizhia <- conflict %>%
dplyr::filter(
civilian_targeting != "",
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
admin1 == "Zaporizhia")
# Create a new column called 'new_event_type'
conflict_zaporizhia$new_event_type <- NA
# Map values based on 'sub_event_type'
conflict_zaporizhia$new_event_type[conflict_zaporizhia$sub_event_type %in% c("Attack", "Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_zaporizhia$sub_event_type[conflict_zaporizhia$sub_event_type %in% c("Attack","Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_zaporizhia$new_event_type[!(conflict_zaporizhia$sub_event_type %in% c("Attack","Shelling/artillery/missile attack", "Air/drone strike", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_zaporizhia <- conflict_zaporizhia %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), new_event_type)
zaporizhia <- subset(ukraine_states_rds, NAME_1 == "Zaporizhzhya")
zaporizhia_map <- ggplot() +
geom_polygon(data=zaporizhia, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
zaporizhia_map

zaporizhia_map +
geom_point(data = number_of_events_zaporizhia, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
geom_point(color="black", shape=21, data = number_of_events_zaporizhia, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Sub-Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Zaporizhia", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Explosive Threats for Civilians in Southern Ukraine
Russian attempts for landings from the Black Sea were unsuccessful.
Russian forces invaded southern Ukraine from the annexed Crimean
peninsula, successfully overtaking the Kherson region and its main city
in March 2022. The Kherson and Mykolaiv regions experienced significant
violence, with artillery strikes leading to high fatality numbers. The
most common types of violence in Kherson were abductions, forced
disappearances, torture, targeting primarily officials, journalists,
activists, and those suspected of pro-Ukrainian views. In June 2022,
Russian forces reportedly abducted about 50 Crimean Tatars from Kherson.
Two significant incidents in the Odesa region include a missile strike
that killed 8 and injured 10 civilians on April 2022, and an airstrike
that killed at least 21 civilians on July 2022.
southern_ukraine_states_name = c("Mykolaiv", "Kherson", "Crimea", "Odesa" )
conflict_southern_ukraine <- conflict %>%
dplyr::filter(
civilian_targeting != "",
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
admin1 %in% southern_ukraine_states_name)
# Create a new column called 'new_event_type'
conflict_southern_ukraine$new_event_type <- NA
# Map values based on 'sub_event_type'
conflict_southern_ukraine$new_event_type[conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")] <- conflict_southern_ukraine$sub_event_type[conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED")]
conflict_southern_ukraine$new_event_type[!(conflict_southern_ukraine$sub_event_type %in% c("Attack", "Abduction/forced disappearance" , "Remote explosive/landmine/IED"))] <- "Other violence"
number_of_events_southern_ukraine <- conflict_southern_ukraine %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), new_event_type)
southern_ukraine <- subset(ukraine_states_rds, NAME_1 %in% southern_ukraine_states_rds_names)
southern_ukraine_map <- ggplot() +
geom_polygon(data=southern_ukraine, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
southern_ukraine_map

southern_ukraine_map +
geom_point(data = number_of_events_southern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=new_event_type)) +
geom_point(color="black", shape=21, data = number_of_events_southern_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=new_event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Sub-Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Southern Ukraine", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Constant Menace from the Skies in Central and Western Ukraine
Over 150 Russian missile, air, and drone strikes have targeted the
Central and West regions, posing a significant threat to civilian
safety. Approximately one-fifth of these strikes hit civilian areas,
leading to over 80 fatalities. Two incidents accounted for most of the
reported fatalities: a missile strike on a shopping mall, in Poltava, on
June 2022, and a missile strike on a Vinnytsia concert hall on July
2022. At least 50 Russian strikes targeted energy infrastructure deep
within Ukraine which caused power outages, with Vinnytsia being one of
the most affected regions.
unique(conflict$admin1)
[1] "Dnipropetrovsk" "Luhansk" "Donetsk" "Kharkiv" "Kherson" "Sumy" "Zaporizhia" "Kyiv City" "Chernihiv"
[10] "Crimea" "Chernivtsi" "Ivano-Frankivsk" "Khmelnytskyi" "Lviv" "Mykolaiv" "Odesa" "Poltava" "Vinnytsia"
[19] "Kirovograd" "Zhytomyr" "Ternopil" "Cherkasy" "Kyiv" "Volyn" NA "Rivne" "Zakarpattia"
central_western_ukraine_states_name <- c("Volyn", "Rivne", "Lviv", "Ternopil", "Khmelnytskyi", "Ivano-Frankivsk", "Zakarpattia", "Chernivtsi", "Vinnytsia", "Cherkasy", "Kirovograd", "Poltava" )
conflict_central_western_ukraine <- conflict %>%
dplyr::filter(
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
sub_event_type == "Shelling/artillery/missile attack",
admin1 %in% central_western_ukraine_states_name
)
number_of_events_central_western_ukraine <- conflict_central_western_ukraine %>%
group_by(latitude, longitude) %>%
summarize(number_of_events = n(), .groups = "drop")
central_western_ukraine <- subset(ukraine_states_rds, NAME_1 %in% central_ukraine_states_rds_names | NAME_1 %in% western_ukraine_states_rds_names)
central_western_ukraine_map <- ggplot() +
geom_polygon(data=central_western_ukraine, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
central_western_ukraine_map

central_western_ukraine_map +
geom_point(color="black", shape=21, fill="darkblue", alpha=0.6, data = number_of_events_central_western_ukraine, aes(x = longitude, y = latitude, size = number_of_events)) +
scale_size_continuous(range = c(1, 10), guide = 'legend', breaks = c(1, 10, 20, 50), labels = c("1", "10", "20", "50+")) +
labs(size = "Number of Events") +
labs(title = "Long-Range Strikes in Central and Western Ukraine", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

Interactive Map
library(leaflet)
ukraine_interactive_map <- leaflet() %>%
addTiles() %>%
setView(lng = 37.7933, lat = 48.1450, zoom = 7)
ukraine_interactive_map
eastern_ukraine_states_names = list("Dnipropetrovsk", "Luhansk", "Donetsk", "Kharkiv", "Zaporizhia")
conflict_eastern_ukraine <- conflict %>%
dplyr::filter(
event_date >= as.Date("2022-02-01") & event_date <= as.Date("2023-01-31"),
event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
admin1 %in% eastern_ukraine_states_names)
events <- data.frame(latitude = conflict_eastern_ukraine$latitude,
longitude = conflict_eastern_ukraine$longitude)
m <- ukraine_interactive_map %>%
addCircleMarkers(data = events,
lng = ~longitude,
lat = ~latitude,
radius = 1,
color = "red",
fill = TRUE,
fillOpacity = 0.8)
# Display the map
m
m2 <- addPolygons(
map = m,
data = east_ukraine_states_rds,
fillColor = "orange",
fillOpacity = 0.2,
color = "black",
weight = 1
)
m2
Pre-Invasion
The Euromaidan protests, which started in late 2013, were primarily
centered in the capital city of Kyiv (Kiev) but spread to other regions
as well. The protests involved clashes between demonstrators and law
enforcement, resulting in instances of violence, injuries, and
fatalities.
Before the Russian invasion the violence in eastern Ukraine was
already concentrated in areas close to the Ukrainian-Russian border,
particularly in the Donetsk and Luhansk regions. Cities such as Donetsk,
Luhansk, Mariupol, and Sloviansk witnessed intense fighting and became
hotspots of violence.
Both sides of the conflict engaged in military operations, including
artillery shelling, sniper attacks, and armed clashes. The violence was
not limited to specific cities but was spread across the
conflict-affected regions.
The conflict resulted in a significant number of civilian casualties
and widespread displacement of residents. Civilians, including those
living in towns and villages near the front lines, faced the risk of
violence and were often caught in the crossfire.
ukraine_map2

centroid <- ukraine_states_rds$centroid <- coordinates(ukraine_states_rds)
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds$NAME_1), color = "black", size = 4)
pi_ukraine_map <- ukraine_map2 +
geom_text(aes(x = centroid[, 1], y = centroid[, 2], label = ukraine_states_rds_names), size=2) + labs(title = "Pre-Invasion Conflicts", fontface="bold") + theme_void() + theme(plot.title = element_text(hjust = 0.5, face = "bold")) + coord_map(projection = "albers", lat0 = 49, lat1 = 54)
pi_ukraine_map

conflict_pi_ukraine <- conflict %>%
dplyr::filter(
event_date <= as.Date("2022-02-01"),
civilian_targeting != ""
)
number_of_events_pi_ukraine <- conflict_pi_ukraine %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), event_type)
pi_ukraine_map +
geom_point(data = number_of_events_pi_ukraine, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
geom_point(color="black", shape=21, data = number_of_events_pi_ukraine, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
scale_size_continuous(range = c(0.1, 10)) +
labs(color = "Event Type", size = "Number of Events") +
labs(title = "Violence targeting Civilians in Pre-Invasion Ukraine", fontface="bold") +
labs(subtitle = "Before February 2022 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))
Coordinate system already present. Adding new coordinate system, which will replace the existing one.

Political Violence in Eastern Ukraine Pre-Invasion
conflict_eastern_ukraine_pi <- conflict %>%
dplyr::filter(
disorder_type == "Political violence",
event_date < as.Date("2022-02-01"),
event_type %in% c("Explosions/Remote violence", "Battles", "Violence against civilians"),
admin1 %in% eastern_ukraine_states_names)
event_counts_eastern_ukraine_pi <- conflict_eastern_ukraine_pi %>%
group_by(longitude, latitude) %>%
reframe(number_of_events = n(), event_type)
eastern_ukraine_map <- ggplot() +
geom_polygon(data=east_ukraine_states_rds, aes(x = long, y = lat, group = group), fill="orange", alpha=0.2, color="black") + guides(fill = "none") + theme_void()
Regions defined for each Polygons
eastern_ukraine_map

centroid <- east_ukraine_states_rds$centroid <- coordinates(east_ukraine_states_rds)
centroid[2] = centroid[2]+0.4
centroid[7] = centroid[7]-0.4
centroid[3] = centroid[3]-0.4
text <- geom_text(data = , aes(x = centroid[, 1], y = centroid[, 2], label = c("Dnipropetrovsk", "Donetsk", "Kharkiv", "Luhansk", "Zaporizhia")), color = "black", size = 4)
eastern_ukraine_map +
geom_point(data = event_counts_eastern_ukraine_pi, aes(x = longitude, y = latitude, size = number_of_events, color=event_type)) +
geom_point(color="black", shape=21, data = event_counts_eastern_ukraine_pi, aes(x = longitude, y = latitude, size = number_of_events, fill=event_type)) +
scale_size_continuous(range = c(0.1, 5)) +
labs(color = "Event Type", size = "Number of Events") +
labs(title = "Political Violence in Eastern Ukraine Pre-Invasion", fontface="bold") +
labs(subtitle = "February 2022 - January 2023 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5)) +
text

conflict_ukraine_pi_riots <- conflict %>%
dplyr::filter(
disorder_type == "Political violence",
event_date < as.Date("2022-02-01"),
event_type == "Riots"
)
ukraine_map2 +
geom_point(color="black", shape=21, fill="orange", alpha=0.6, data = conflict_ukraine_pi_riots, aes(x = longitude, y = latitude, size = 1)) +
labs(title = "Riots in Pre-Invasion Ukraine", fontface="bold") +
labs(subtitle = "Before February 2022 ") +
coord_map(projection = "albers", lat0 = 49, lat1 = 54) +
guides(size = "none") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, face="bold"), plot.subtitle = element_text(hjust = 0.5))

LS0tCmF1dGhvcjogIkVsaWYgw4dheXNhciwgR2lyYXkgQ2/Fn2t1biwgU3VkZSBCdWtldCBLaXByaSwgWmV5bmVwIEFrYW50Igp0aXRsZTogIkVjb24gNDk0IFNwYXRpYWwgRGF0YSBTY2llbmNlIFByb2plY3QgLSBBbmFseXNpcyBvZiBBQ0xFRCBSZXBvcnQgV2FyIGluIFVrcmFpbmUiCm91dHB1dDogaHRtbF9ub3RlYm9vawppbnN0aXR1dGU6ICJTYWJhbmNpIFVuaXZlcnNpdHkiCmZvcm1hdDoKICBwZGY6IGRlZmF1bHQKZWRpdG9yOiB2aXN1YWwKLS0tCgojIEVDT04gNDk0IC0gU3BhdGlhbCBEYXRhIFNjaWVuY2UgUHJvamVjdAoKT3VyIHByb2plY3QgYWltZWQgdG8gYW5hbHl6ZSB0aGUgVWtyYWluZSBjb25mbGljdCB1c2luZyBzcGF0aWFsIGFuYWx5c2lzIGFuZCBtYXBzIGdlbmVyYXRlZCB0aHJvdWdoIGRhdGEgZnJvbSBBQ0xFRCAoQXJtZWQgQ29uZmxpY3QgTG9jYXRpb24gJiBFdmVudCBEYXRhIFByb2plY3QpLiBGb2N1c2luZyBvbiB0aGUgdmlvbGVuY2UgdGFyZ2V0aW5nIGNpdmlsaWFucyBhZnRlciBpbnZhc2lvbiBvZiBSdXNzaWEgaW50byBVa3JhaW5lLCB3ZSB1dGlsaXplZCBSIHByb2dyYW1taW5nIHRvIGV4dHJhY3QgYW5kIHZpc3VhbGl6ZSB0aGUgY29uZmxpY3QgZGF0YSwgZW5hYmxpbmcgdXMgdG8gcHJlc2VudCBhIGNvbXByZWhlbnNpdmUgb3ZlcnZpZXcgb2YgdGhlIGV2ZW50cyBhbmQgdGhlaXIgc3BhdGlhbCBkaXN0cmlidXRpb24uCgpgYGB7cn0KbGlicmFyeShzcCkKbGlicmFyeShyYXN0ZXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY29uZmxpY3RlZCkKYGBgCgojIyBJbnRyb2R1Y3Rpb24KCi0gICBSdXNzaWEgaW52YWRlZCBVa3JhaW5lIGluIEZlYnJ1YXJ5IDIwMjIsIHJlc3VsdGluZyBpbiB0aGUgaGlnaGVzdCBsZXZlbHMgb2YgcG9saXRpY2FsIHZpb2xlbmNlIHJlY29yZGVkIGluIGEgc2luZ2xlIGNvdW50cnkgYnkgQUNMRUQuCgotICAgQ2l2aWxpYW5zIGluIFVrcmFpbmUgaGF2ZSBmYWNlZCBzaGVsbGluZywgaW5kaXNjcmltaW5hdGUgc3RyaWtlcywgZGVsaWJlcmF0ZSBhdHRhY2tzLCBhbmQgaGFyc2ggdHJlYXRtZW50IGluIG9jY3VwaWVkIGFyZWFzLgoKLSAgIFJ1c3NpYW4gZm9yY2VzIHRhcmdldGVkIEt5aXYgYnV0IHJldHJlYXRlZCBpbiBub3J0aGVybiBVa3JhaW5lIHdoaWxlIHF1aWNrbHkgc2VpemluZyB0ZXJyaXRvcmllcyBpbiBzb3V0aGVybiBhbmQgZWFzdGVybiByZWdpb25zLgoKLSAgIE92ZXIgNSwwMDAgcmVwb3J0ZWQgY2l2aWxpYW4gZmF0YWxpdGllcyBoYXZlIG9jY3VycmVkLCBidXQgdGhlIGFjdHVhbCB0b2xsIGlzIGxpa2VseSBtdWNoIGhpZ2hlci4KCi0gICBEaWZmZXJlbnQgcmVnaW9ucyBvZiBVa3JhaW5lIGV4cGVyaWVuY2VkIHZhcnlpbmcgbGV2ZWxzIG9mIHZpb2xlbmNlIGFuZCBvY2N1cGF0aW9uIGR1cmluZyB0aGUgY29uZmxpY3QuCgpgYGB7cn0KI3VrcmFpbmVfc3RhdGVzX3JkcyA8LSByYXN0ZXI6OmdldERhdGEoJ0dBRE0nLCBjb3VudHJ5ID0gIlVLUiIsIGxldmVsID0gMSkKdWtyYWluZV9zdGF0ZXNfcmRzID0gcmVhZFJEUygidWtyYWluZS5yZHMiKSAjaHR0cHM6Ly9nYWRtLm9yZy9kb3dubG9hZF9jb3VudHJ5Lmh0bWwKYGBgCgpgYGB7cn0KdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXVrcmFpbmVfc3RhdGVzX3JkcywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbCA9IGlkKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGEgPSAwLjYgKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKQp1a3JhaW5lX21hcApgYGAKCmBgYHtyfQplYXN0X3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJEbmlwcm9wZXRyb3ZzJ2siLCAiRG9uZXRzJ2siLCAiTHVoYW5zJ2siICwgICJLaGFya2l2IiwgIlphcG9yaXpoemh5YSIpCgplYXN0X3VrcmFpbmVfc3RhdGVzX3JkcyA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgJWluJSBlYXN0X3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKYGBgCgpgYGB7cn0Kc291dGhfdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzIDwtIGxpc3QoIkNoZXJuaWhpdiIsICJLaWV2IiwgIktpZXYgQ2l0eSIsICJaaHl0b215ciIsICJTdW15IikKc291dGhfdWtyYWluZV9zdGF0ZXNfcmRzIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIHNvdXRoX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKYGBgCgpgYGB7cn0KY2VudHJhbF91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMgPC0gbGlzdCgiQ2hlcmthc3kiLCAiS2lyb3ZvaHJhZCIsICJQb2x0YXZhIiwgIlZpbm55dHN5YSIpCmNlbnRyYWxfdWtyYWluZV9zdGF0ZXNfcmRzIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIGNlbnRyYWxfdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzKQpgYGAKCmBgYHtyfQp3ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJWb2x5biIsICJDaGVybml2dHNpIiwgIkl2YW5vLUZyYW5raXZzJ2siLCAiS2htZWwnbnl0cydreXkiLCAiUml2bmUiLCAiTCd2aXYiLCAiVGVybm9waWwnIiwgIlRyYW5zY2FycGF0aGlhIikKd2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHMgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xICVpbiUgd2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMpCmBgYAoKYGBge3J9CnNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyA8LSBsaXN0KCJDcmltZWEiLCAiS2hlcnNvbiIsICAiTXlrb2xheWl2IiwgIk9kZXNzYSIpCnNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3JkcyA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgJWluJSBzb3V0aGVybl91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMpCmBgYAoKYGBge3J9CnVrcmFpbmVfbWFwMiA8LSB1a3JhaW5lX21hcCArIAogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0icmVkIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9c291dGhfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0iYmxhY2siLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsKICBnZW9tX3BvbHlnb24oZGF0YT1jZW50cmFsX3VrcmFpbmVfc3RhdGVzX3JkcywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9ImRhcmtibHVlIiwgYWxwaGE9MC40LCBjb2xvcj0iYmxhY2siKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9d2VzdGVybl91a3JhaW5lX3N0YXRlc19yZHMsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJsaWdodGJsdWUiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsKICBnZW9tX3BvbHlnb24oZGF0YT1zb3V0aGVybl91a3JhaW5lX3N0YXRlc19yZHMsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpCgp1a3JhaW5lX21hcDIKYGBgCgpgYGB7cn0KY2VudHJvaWQgPC0gdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKHVrcmFpbmVfc3RhdGVzX3JkcykKdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzIDwtIHVrcmFpbmVfc3RhdGVzX3JkcyROQU1FXzEKYGBgCgpgYGB7cn0KdWtyYWluZV9tYXAzIDwtIHVrcmFpbmVfbWFwMiArIAogIGdlb21fdGV4dChhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IHVrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcyksIHNpemU9MikgKyBsYWJzKHRpdGxlID0gIlJlZ2lvbnMgb2YgVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSkgKyAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpCnVrcmFpbmVfbWFwMwpgYGAKCiMjIENvbmZsaWN0IERhdGEgKEFDTEVEKQoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMgPSBsaXN0KCJEbmlwcm9wZXRyb3ZzayIsICJMdWhhbnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJaYXBvcml6aGlhIikKYGBgCgpgYGB7cn0KY29uZmxpY3QgPC0gcmVhZF9jc3YoJ3VrcmFpbmUuY3N2Jywgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkKY29uZmxpY3QkZXZlbnRfZGF0ZSA8LSBhcy5EYXRlKGNvbmZsaWN0JGV2ZW50X2RhdGUsIGZvcm1hdCA9ICIlZCAlQiAlWSIpCmBgYAoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRhZG1pbjEpCmBgYAoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRldmVudF90eXBlKQpgYGAKCmBgYHtyfQp1bmlxdWUoY29uZmxpY3Qkc3ViX2V2ZW50X3R5cGUpCmBgYAoKIyMgQXBwYXJlbnQgV2FyIENyaW1lcyBpbiBOb3J0aGVybiBVa3JhaW5lCgojIyBIZWF2eSBGaWdodGluZyBBbG9uZyB0aGUgRnJvbnRsaW5lIGluIEVhc3Rlcm4gVWtyYWluZQoKIyMjIFBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUKCkVhc3Rlcm4gVWtyYWluZSBmYWNlcyB1bnByZWNlZGVudGVkIHZpb2xlbmNlLCB3aXRoIHRocmVlLXF1YXJ0ZXJzIG9mIHBvbGl0aWNhbCB2aW9sZW5jZSBldmVudHMgb2NjdXJyaW5nIGluIHRoZSByZWdpb24sIHByaW1hcmlseSBkdWUgdG8gc2hlbGxpbmcsIGFydGlsbGVyeSwgYW5kIG1pc3NpbGUgYXR0YWNrcy4KRGVzcGl0ZSByZWxhdGl2ZSBkaXN0YW5jZSBmcm9tIHRoZSBmcm9udGxpbmUsIHRoZSBEbmlwcm9wZXRyb3ZzayByZWdpb24gcmVtYWlucyBhdCByaXNrLCBhcyBSdXNzaWEgY29udGludWVzIGFpciBhbmQgbWlzc2lsZSBzdHJpa2VzLCBleGVtcGxpZmllZCBieSB0aGUgZGVhZGx5IGluY2lkZW50IGluIERuaXBybyBvbiAxNCBKYW51YXJ5IDIwMjMuCgoKYGBge3J9CmNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgJWluJSBjKCJFeHBsb3Npb25zL1JlbW90ZSB2aW9sZW5jZSIsICJCYXR0bGVzIiwgIlZpb2xlbmNlIGFnYWluc3QgY2l2aWxpYW5zIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBlYXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWVzKQpgYGAKCmBgYHtyfQpldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lIDwtIGNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKSArIHRoZW1lX3ZvaWQoKQplYXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyb2lkIDwtIGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzKQpjZW50cm9pZFsyXSA9IGNlbnRyb2lkWzJdKzAuNApjZW50cm9pZFs3XSA9IGNlbnRyb2lkWzddLTAuNApjZW50cm9pZFszXSA9IGNlbnRyb2lkWzNdLTAuNAp0ZXh0IDwtIGdlb21fdGV4dChkYXRhID0gLCBhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IGMoIkRuaXByb3BldHJvdnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJMdWhhbnNrIiwgIlphcG9yaXpoaWEiKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IGV2ZW50X2NvdW50c19lYXN0ZXJuX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCA1KSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJGZWJydWFyeSAyMDIyIC0gSmFudWFyeSAyMDIzICIpICsKICBjb29yZF9tYXAocHJvamVjdGlvbiA9ICJhbGJlcnMiLCBsYXQwID0gNDksIGxhdDEgPSA1NCkgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogIHRleHQKYGBgCgojIyMgQ29uZmxpY3QgaW4gS2hhcmtpdgoKQWx0aG91Z2ggUnVzc2lhbiBmb3JjZXMgd2VyZSB1bmFibGUgdG8gYnJlYWsgVWtyYWluaWFuIGRlZmVuc2VzIGFyb3VuZCB0aGUgY2l0eSBvZiBLaGFya2l2LCB0aGV5IGhhZCBvY2N1cGllZCB0aGUgYnVsayBvZiB0aGUgcmVnaW9u4oCZcyBub3J0aGVybiBhbmQgZWFzdGVybiBwYXJ0cyBieSBBcHJpbCAyMDIyLCBpbmNsdWRpbmcgSXppdW0g4oCTIGEgY3JpdGljYWwgdHJhbnNwb3J0IGh1YgpVa3JhaW5lIGxpYmVyYXRlZCBhbG1vc3QgdGhlIGVudGlyZSByZWdpb24gaW4gYSBzdXJwcmlzZSBjb3VudGVyLW9mZmVuc2l2ZSBpbiBTZXB0ZW1iZXIgMjAyMi4KT2Ygb3ZlciA4MDAgZXZlbnRzIHRhcmdldGluZyBjaXZpbGlhbnMsIGFib3V0IHRocmVlLXF1YXJ0ZXJzIGNvbnN0aXR1dGVkIGFydGlsbGVyeSwgbWlzc2lsZSwgYW5kIGFpcnN0cmlrZSBldmVudHMsIHdoaWNoIGFsc28gcmVzdWx0ZWQgaW4gdGhlIG1ham9yaXR5IG9mIHJlcG9ydGVkIGNpdmlsaWFuIGZhdGFsaXRpZXMgcmVjb3JkZWQgaW4gdGhlIHJlZ2lvbi4gQWJvdXQgYSB0aGlyZCBvZiB0aGVzZSBvY2N1cnJlZCBpbiBNYXJjaCAyMDIyIGFsb25lLgoKCgpgYGB7cn0KY29uZmxpY3Rfa2hhcmtpdiA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgY2l2aWxpYW5fdGFyZ2V0aW5nICE9ICIiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGFkbWluMSA9PSAiS2hhcmtpdiIpCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBjYWxsZWQgJ25ld19ldmVudF90eXBlJwpjb25mbGljdF9raGFya2l2JG5ld19ldmVudF90eXBlIDwtIE5BCgojIE1hcCB2YWx1ZXMgYmFzZWQgb24gJ3N1Yl9ldmVudF90eXBlJwpjb25mbGljdF9raGFya2l2JG5ld19ldmVudF90eXBlW2NvbmZsaWN0X2toYXJraXYkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIsICJBdHRhY2siKV0gPC0gY29uZmxpY3Rfa2hhcmtpdiRzdWJfZXZlbnRfdHlwZVtjb25mbGljdF9raGFya2l2JHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiLCAiQXR0YWNrIildCmNvbmZsaWN0X2toYXJraXYkbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9raGFya2l2JHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiLCAiQXR0YWNrIikpXSA8LSAiT3RoZXIgdmlvbGVuY2UiCmBgYAoKYGBge3J9Cm51bWJlcl9vZl9ldmVudHNfa2hhcmtpdiA8LSBjb25mbGljdF9raGFya2l2ICU+JQogIGdyb3VwX2J5KGxvbmdpdHVkZSwgbGF0aXR1ZGUpICU+JQogIHJlZnJhbWUobnVtYmVyX29mX2V2ZW50cyA9IG4oKSwgbmV3X2V2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmtoYXJraXYgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xID09ICJLaGFya2l2IikKa2hhcmtpdl9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWtoYXJraXYsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCmtoYXJraXZfbWFwCmBgYAoKYGBge3J9CmtoYXJraXZfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2toYXJraXYsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19raGFya2l2LCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gS2hhcmtpdiIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyMgQ29uZmxpY3QgaW4gTHVoYW5zawoKVGhlIHNoZWVyIHNjYWxlIG9mIGFydGlsbGVyeSwgbWlzc2lsZSwgYW5kIGFpciBhdHRhY2tzIGluZmxpY3RlZCBvbiBMdWhhbnNrIHJlZ2lvbiBhcyB3ZWxsIGFzIGludGVuc2UgY2xvc2UgY29tYmF0IGJyb3VnaHQgYWJvdXQgaW1tZW5zZSBzdWZmZXJpbmcgZm9yIHRoZSBjaXZpbGlhbnMuCk9uIDExIE1hcmNoIDIwMjIsIDU2IGVsZGVybHkgcGF0aWVudHMgcmVwb3J0ZWRseSBkaWVkIGR1cmluZyB0aGUgc2hlbGxpbmcgb2YgYSBudXJzaW5nIGhvbWUgaW4gS3JlbWlubmEsIGFuZCBhdCBsZWFzdCA2MCBwZW9wbGUgd2VyZSBraWxsZWQgaW4gYW4gYWlyc3RyaWtlIG9uIGEgc2Nob29sIHVzZWQgYXMgYSBzaGVsdGVyIGluIEJpbG9ob3JpdmthIG9uIDcgTWF5IDIwMjIuIE92ZXIgNTAgY2l2aWxpYW5zIHdlcmUgYWxzbyBraWxsZWQgZHVyaW5nIHRoZSBzaGVsbGluZyBvZiBTZXZlcm9kb25ldHNrIGluIE1hcmNoIGFuZCBNYXkgMjAyMi4gCkZvbGxvd2luZyB0aGUgUnVzc2lhbiBvY2N1cGF0aW9uIG9mIHRoZSByZWdpb24gaW4gc3VtbWVyIDIwMjIsIHRoZSBudW1iZXIgb2YgcmVwb3J0cyBvZiBjaXZpbGlhbnMgYmVpbmcgdGFyZ2V0ZWQgd2VudCBzaGFycGx5IGRvd247IHRob3VnaCB0aGUgcmVnaW9uIGhhcyByZW1haW5lZCBoaWdobHkga2luZXRpYywgZXNwZWNpYWxseSBzaW5jZSBhdXR1bW4uIAoKCmBgYHtyfQpjb25mbGljdF9sdWhhbnNrIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBjaXZpbGlhbl90YXJnZXRpbmcgIT0gIiIsCiAgICAgICAgICAgICAgICBldmVudF9kYXRlID49IGFzLkRhdGUoIjIwMjItMDItMDEiKSAmIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMy0wMS0zMSIpLAogICAgICAgICAgICAgICAgYWRtaW4xID09ICJMdWhhbnNrIikKYGBgCgpgYGB7cn0KIyBDcmVhdGUgYSBuZXcgY29sdW1uIGNhbGxlZCAnbmV3X2V2ZW50X3R5cGUnCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGUgPC0gTkEKCiMgTWFwIHZhbHVlcyBiYXNlZCBvbiAnc3ViX2V2ZW50X3R5cGUnCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGVbY29uZmxpY3RfbHVoYW5zayRzdWJfZXZlbnRfdHlwZSAlaW4lIGMoIlNoZWxsaW5nL2FydGlsbGVyeS9taXNzaWxlIGF0dGFjayIsICJBaXIvZHJvbmUgc3RyaWtlIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiQXR0YWNrIildIDwtIGNvbmZsaWN0X2x1aGFuc2skc3ViX2V2ZW50X3R5cGVbY29uZmxpY3RfbHVoYW5zayRzdWJfZXZlbnRfdHlwZSAlaW4lIGMoIlNoZWxsaW5nL2FydGlsbGVyeS9taXNzaWxlIGF0dGFjayIsICJBaXIvZHJvbmUgc3RyaWtlIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiQXR0YWNrIildCmNvbmZsaWN0X2x1aGFuc2skbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9sdWhhbnNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJBdHRhY2siKSldIDwtICJPdGhlciB2aW9sZW5jZSIKYGBgCgpgYGB7cn0KbnVtYmVyX29mX2V2ZW50c19sdWhhbnNrIDwtIGNvbmZsaWN0X2x1aGFuc2sgJT4lCiAgZ3JvdXBfYnkobG9uZ2l0dWRlLCBsYXRpdHVkZSkgJT4lCiAgcmVmcmFtZShudW1iZXJfb2ZfZXZlbnRzID0gbigpLCBuZXdfZXZlbnRfdHlwZSkKYGBgCgpgYGB7cn0KbHVoYW5zayA8LSBzdWJzZXQodWtyYWluZV9zdGF0ZXNfcmRzLCBOQU1FXzEgPT0gIkx1aGFucydrIikKbHVoYW5za19tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWx1aGFuc2ssICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCmx1aGFuc2tfbWFwCmBgYAoKYGBge3J9Cmx1aGFuc2tfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2x1aGFuc2ssIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19sdWhhbnNrLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gTHVoYW5zayIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyMgQ29uZmxpY3QgaW4gRG9uZXRzawoKQUNMRUQgcmVjb3JkcyBvdmVyIDE2LDAwMCBldmVudHMgaW4gRG9uZXRzayByZWdpb24sIG9mIHdoaWNoIG92ZXIgMTIsMDAwIHdlcmUgYXR0cmlidXRlZCB0byBzaGVsbGluZywgYXJ0aWxsZXJ5LCBtaXNzaWxlLCBhbmQgYWlyc3RyaWtlIGV2ZW50cy4gT25seSBhIHNtYWxsIHBvcnRpb24gb2YgdGhlc2UgZXZlbnRzIOKAkyBhYm91dCA4MDAg4oCTIGNvdWxkIGJlIGF0dHJpYnV0ZWQgdG8gdGhlIGRpcmVjdCB0YXJnZXRpbmcgb2YgY2l2aWxpYW4uClRoZSBjaXR5IG9mIE1hcml1cG9sIHdhcyB0aGUgc2l0ZSBvZiBzZXZlcmFsIG1hc3MgY2FzdWFsdHkgZXZlbnRzIGFoZWFkIG9mIHRoZSBSdXNzaWFuIG9jY3VwYXRpb24uIApNYXNzIGNhc3VhbHR5IGV2ZW50cyBkdWUgdG8gbG9uZy1yYW5nZSBtaXNzaWxlIGFuZCBhcnRpbGxlcnkgc3RyaWtlcyBvY2N1cnJlZCBpbiBvdGhlciBwYXJ0cyBvZiB0aGUgcmVnaW9uIGFuZCBvbiBib3RoIHNpZGVzIG9mIHRoZSBsaW5lIG9mIGNvbnRhY3QuCgoKYGBge3J9CmNvbmZsaWN0X2RvbmV0c2sgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIiwKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPj0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpICYgZXZlbnRfZGF0ZSA8PSBhcy5EYXRlKCIyMDIzLTAxLTMxIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgPT0gIkRvbmV0c2siKQpgYGAKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkICduZXdfZXZlbnRfdHlwZScKY29uZmxpY3RfZG9uZXRzayRuZXdfZXZlbnRfdHlwZSA8LSBOQQoKIyBNYXAgdmFsdWVzIGJhc2VkIG9uICdzdWJfZXZlbnRfdHlwZScKY29uZmxpY3RfZG9uZXRzayRuZXdfZXZlbnRfdHlwZVtjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpXSA8LSBjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlW2NvbmZsaWN0X2RvbmV0c2skc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJBYmR1Y3Rpb24vZm9yY2VkIGRpc2FwcGVhcmFuY2UiICwgIlJlbW90ZSBleHBsb3NpdmUvbGFuZG1pbmUvSUVEIildCmNvbmZsaWN0X2RvbmV0c2skbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF9kb25ldHNrJHN1Yl9ldmVudF90eXBlICVpbiUgYygiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX2RvbmV0c2sgPC0gY29uZmxpY3RfZG9uZXRzayAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQpkb25ldHNrIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSA9PSAiRG9uZXRzJ2siKQpkb25ldHNrX21hcCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9wb2x5Z29uKGRhdGE9ZG9uZXRzaywgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuMiwgY29sb3I9ImJsYWNrIikgKyBndWlkZXMoZmlsbCA9ICJub25lIikgKyB0aGVtZV92b2lkKCkKZG9uZXRza19tYXAKYGBgCgpgYGB7cn0KZG9uZXRza19tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IG51bWJlcl9vZl9ldmVudHNfZG9uZXRzaywgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgc2l6ZSA9IG51bWJlcl9vZl9ldmVudHMsIGNvbG9yPW5ld19ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2RvbmV0c2ssIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBmaWxsPW5ld19ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCAxMCkpICsKICBsYWJzKGNvbG9yID0gIlN1Yi1FdmVudCBUeXBlIiwgc2l6ZSA9ICJOdW1iZXIgb2YgRXZlbnRzIikgKwogIGxhYnModGl0bGUgPSAiVmlvbGVuY2UgdGFyZ2V0aW5nIENpdmlsaWFucyBpbiBEb25ldHNrIiwgZm9udGZhY2U9ImJvbGQiKSArIAogIGxhYnMoc3VidGl0bGUgPSAiRmVicnVhcnkgMjAyMiAtIEphbnVhcnkgMjAyMyAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMjIyBDb25mbGljdCBpbiBaYXBvcml6aGlhCgpSdXNzaWFuIGZvcmNlcyBvY2N1cGllZCBtb3N0IG9mIHRoZSBaYXBvcml6aGlhIHJlZ2lvbiBpbiB0aGUgZmlyc3Qgd2Vla3Mgb2YgdGhlIGludmFzaW9uLCBjYXB0dXJpbmcgdGhlIGVudGlyZSBzaG9yZSBvZiB0aGUgU2VhIG9mIEF6b3YsIGluY2x1ZGluZyB0aGUgVWtyYWluaWFuIG5hdnkgYmFzZSBpbiBCZXJkaWFuc2ssIGFuZCBhbiBhcmVhIHN0cmV0Y2hpbmcgYmV0d2VlbiB0aGUgS2hlcnNvbiBhbmQgc291dGhlcm4gRG9uZXRzayByZWdpb25zIHVwIHRvIHRoZSBEbmlwcm8gcml2ZXIsIGluY2x1ZGluZyB0aGUgc2Vjb25kLWxhcmdlc3QgdG93biBvZiBNZWxpdG9wb2wuClVrcmFpbmlhbiBmb3JjZXMgc3RvcHBlZCBSdXNzaWFuIGZvcmNlcyBpbiB0aGUgYXJlYSBvZiBPcmlraGl2IGFuZCBIdWxpYWlwb2xlCkFsdGhvdWdoIHNoZWxsaW5nIGFuZCBhaXIgYW5kIGRyb25lIHN0cmlrZXMgaGF2ZSBhY2NvdW50ZWQgZm9yIGFib3V0IGhhbGYgb2YgZXZlbnRzIHRhcmdldGluZyBjaXZpbGlhbnMgaW4gdGhlIFphcG9yaXpoaWEgcmVnaW9uLCBjaXZpbGlhbnMgaGF2ZSBhbHNvIGJlZW4gdGhlIHN1YmplY3Qgb2YgZGlyZWN0IGF0dGFja3MuIFRoZXNlIGluY2x1ZGUgZmlyaW5nIGF0IHZlaGljbGVzIGNhcnJ5aW5nIGV2YWN1YXRpbmcgY2l2aWxpYW5zLCBhcyB3ZWxsIGFzIHRvcnR1cmUgYW5kIGV4ZWN1dGlvbi4KSW4gYXJlYXMgdW5kZXIgUnVzc2lhbiBvY2N1cGF0aW9uLCByZXBvcnRzIG9mIHRoZSBhYmR1Y3Rpb24gb2YgbG9jYWwgb2ZmaWNpYWxzLCB0ZWFjaGVycywgam91cm5hbGlzdHMsIFVrcmFpbmlhbiBhcm15IHZldGVyYW5zLCBhbmQgY2l2aWwgYWN0aXZpc3RzIGFyZSBjb21tb24uCgoKCgpgYGB7cn0KY29uZmxpY3RfemFwb3JpemhpYSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgY2l2aWxpYW5fdGFyZ2V0aW5nICE9ICIiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIGFkbWluMSA9PSAiWmFwb3JpemhpYSIpCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBjYWxsZWQgJ25ld19ldmVudF90eXBlJwpjb25mbGljdF96YXBvcml6aGlhJG5ld19ldmVudF90eXBlIDwtIE5BCgojIE1hcCB2YWx1ZXMgYmFzZWQgb24gJ3N1Yl9ldmVudF90eXBlJwpjb25mbGljdF96YXBvcml6aGlhJG5ld19ldmVudF90eXBlW2NvbmZsaWN0X3phcG9yaXpoaWEkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCAiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpXSA8LSBjb25mbGljdF96YXBvcml6aGlhJHN1Yl9ldmVudF90eXBlW2NvbmZsaWN0X3phcG9yaXpoaWEkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLCAiQWlyL2Ryb25lIHN0cmlrZSIsICJBYmR1Y3Rpb24vZm9yY2VkIGRpc2FwcGVhcmFuY2UiICwgIlJlbW90ZSBleHBsb3NpdmUvbGFuZG1pbmUvSUVEIildCmNvbmZsaWN0X3phcG9yaXpoaWEkbmV3X2V2ZW50X3R5cGVbIShjb25mbGljdF96YXBvcml6aGlhJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwiU2hlbGxpbmcvYXJ0aWxsZXJ5L21pc3NpbGUgYXR0YWNrIiwgIkFpci9kcm9uZSBzdHJpa2UiLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3phcG9yaXpoaWEgPC0gY29uZmxpY3RfemFwb3JpemhpYSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQp6YXBvcml6aGlhIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSA9PSAiWmFwb3Jpemh6aHlhIikKemFwb3JpemhpYV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXphcG9yaXpoaWEsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCnphcG9yaXpoaWFfbWFwCmBgYAoKYGBge3J9CnphcG9yaXpoaWFfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3phcG9yaXpoaWEsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c196YXBvcml6aGlhLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gWmFwb3JpemhpYSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBFeHBsb3NpdmUgVGhyZWF0cyBmb3IgQ2l2aWxpYW5zIGluIFNvdXRoZXJuIFVrcmFpbmUKClJ1c3NpYW4gYXR0ZW1wdHMgZm9yIGxhbmRpbmdzIGZyb20gdGhlIEJsYWNrIFNlYSB3ZXJlIHVuc3VjY2Vzc2Z1bC4KUnVzc2lhbiBmb3JjZXMgaW52YWRlZCBzb3V0aGVybiBVa3JhaW5lIGZyb20gdGhlIGFubmV4ZWQgQ3JpbWVhbiBwZW5pbnN1bGEsIHN1Y2Nlc3NmdWxseSBvdmVydGFraW5nIHRoZSBLaGVyc29uIHJlZ2lvbiBhbmQgaXRzIG1haW4gY2l0eSBpbiBNYXJjaCAyMDIyLgpUaGUgS2hlcnNvbiBhbmQgTXlrb2xhaXYgcmVnaW9ucyBleHBlcmllbmNlZCBzaWduaWZpY2FudCB2aW9sZW5jZSwgd2l0aCBhcnRpbGxlcnkgc3RyaWtlcyBsZWFkaW5nIHRvIGhpZ2ggZmF0YWxpdHkgbnVtYmVycy4KVGhlIG1vc3QgY29tbW9uIHR5cGVzIG9mIHZpb2xlbmNlIGluIEtoZXJzb24gd2VyZSBhYmR1Y3Rpb25zLCBmb3JjZWQgZGlzYXBwZWFyYW5jZXMsIHRvcnR1cmUsIHRhcmdldGluZyBwcmltYXJpbHkgb2ZmaWNpYWxzLCBqb3VybmFsaXN0cywgYWN0aXZpc3RzLCBhbmQgdGhvc2Ugc3VzcGVjdGVkIG9mIHByby1Va3JhaW5pYW4gdmlld3MuCkluIEp1bmUgMjAyMiwgUnVzc2lhbiBmb3JjZXMgcmVwb3J0ZWRseSBhYmR1Y3RlZCBhYm91dCA1MCBDcmltZWFuIFRhdGFycyBmcm9tIEtoZXJzb24uClR3byBzaWduaWZpY2FudCBpbmNpZGVudHMgaW4gdGhlIE9kZXNhIHJlZ2lvbiBpbmNsdWRlIGEgbWlzc2lsZSBzdHJpa2UgdGhhdCBraWxsZWQgOCBhbmQgaW5qdXJlZCAxMCBjaXZpbGlhbnMgb24gQXByaWwgMjAyMiwgYW5kIGFuIGFpcnN0cmlrZSB0aGF0IGtpbGxlZCBhdCBsZWFzdCAyMSBjaXZpbGlhbnMgb24gSnVseSAyMDIyLgoKCgpgYGB7cn0Kc291dGhlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZSA9IGMoIk15a29sYWl2IiwgIktoZXJzb24iLCAiQ3JpbWVhIiwgIk9kZXNhIiApCmNvbmZsaWN0X3NvdXRoZXJuX3VrcmFpbmUgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIiwKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPj0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpICYgZXZlbnRfZGF0ZSA8PSBhcy5EYXRlKCIyMDIzLTAxLTMxIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBzb3V0aGVybl91a3JhaW5lX3N0YXRlc19uYW1lKQpgYGAKCmBgYHtyfQojIENyZWF0ZSBhIG5ldyBjb2x1bW4gY2FsbGVkICduZXdfZXZlbnRfdHlwZScKY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZSA8LSBOQQoKIyBNYXAgdmFsdWVzIGJhc2VkIG9uICdzdWJfZXZlbnRfdHlwZScKY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZVtjb25mbGljdF9zb3V0aGVybl91a3JhaW5lJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiKV0gPC0gY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRzdWJfZXZlbnRfdHlwZVtjb25mbGljdF9zb3V0aGVybl91a3JhaW5lJHN1Yl9ldmVudF90eXBlICVpbiUgYygiQXR0YWNrIiwgIkFiZHVjdGlvbi9mb3JjZWQgZGlzYXBwZWFyYW5jZSIgLCAiUmVtb3RlIGV4cGxvc2l2ZS9sYW5kbWluZS9JRUQiKV0KY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSRuZXdfZXZlbnRfdHlwZVshKGNvbmZsaWN0X3NvdXRoZXJuX3VrcmFpbmUkc3ViX2V2ZW50X3R5cGUgJWluJSBjKCJBdHRhY2siLCAiQWJkdWN0aW9uL2ZvcmNlZCBkaXNhcHBlYXJhbmNlIiAsICJSZW1vdGUgZXhwbG9zaXZlL2xhbmRtaW5lL0lFRCIpKV0gPC0gIk90aGVyIHZpb2xlbmNlIgpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3NvdXRoZXJuX3VrcmFpbmUgPC0gY29uZmxpY3Rfc291dGhlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIG5ld19ldmVudF90eXBlKQpgYGAKCmBgYHtyfQpzb3V0aGVybl91a3JhaW5lIDwtIHN1YnNldCh1a3JhaW5lX3N0YXRlc19yZHMsIE5BTUVfMSAlaW4lIHNvdXRoZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKc291dGhlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPXNvdXRoZXJuX3VrcmFpbmUsICBhZXMoeCA9IGxvbmcsIHkgPSBsYXQsIGdyb3VwID0gZ3JvdXApLCBmaWxsPSJvcmFuZ2UiLCBhbHBoYT0wLjIsIGNvbG9yPSJibGFjayIpICsgZ3VpZGVzKGZpbGwgPSAibm9uZSIpICsgdGhlbWVfdm9pZCgpCnNvdXRoZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CnNvdXRoZXJuX3VrcmFpbmVfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3NvdXRoZXJuX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1uZXdfZXZlbnRfdHlwZSkpICsKICBnZW9tX3BvaW50KGNvbG9yPSJibGFjayIsIHNoYXBlPTIxLCBkYXRhID0gbnVtYmVyX29mX2V2ZW50c19zb3V0aGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1uZXdfZXZlbnRfdHlwZSkpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgMTApKSArCiAgbGFicyhjb2xvciA9ICJTdWItRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gU291dGhlcm4gVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBDb25zdGFudCBNZW5hY2UgZnJvbSB0aGUgU2tpZXMgaW4gQ2VudHJhbCBhbmQgV2VzdGVybiBVa3JhaW5lCgpPdmVyIDE1MCBSdXNzaWFuIG1pc3NpbGUsIGFpciwgYW5kIGRyb25lIHN0cmlrZXMgaGF2ZSB0YXJnZXRlZCB0aGUgQ2VudHJhbCBhbmQgV2VzdCByZWdpb25zLCBwb3NpbmcgYSBzaWduaWZpY2FudCB0aHJlYXQgdG8gY2l2aWxpYW4gc2FmZXR5LgpBcHByb3hpbWF0ZWx5IG9uZS1maWZ0aCBvZiB0aGVzZSBzdHJpa2VzIGhpdCBjaXZpbGlhbiBhcmVhcywgbGVhZGluZyB0byBvdmVyIDgwIGZhdGFsaXRpZXMuClR3byBpbmNpZGVudHMgYWNjb3VudGVkIGZvciBtb3N0IG9mIHRoZSByZXBvcnRlZCBmYXRhbGl0aWVzOiBhIG1pc3NpbGUgc3RyaWtlIG9uIGEgc2hvcHBpbmcgbWFsbCwgaW4gUG9sdGF2YSwgb24gSnVuZSAyMDIyLCBhbmQgYSBtaXNzaWxlIHN0cmlrZSBvbiBhIFZpbm55dHNpYSBjb25jZXJ0IGhhbGwgb24gSnVseSAyMDIyLgpBdCBsZWFzdCA1MCBSdXNzaWFuIHN0cmlrZXMgdGFyZ2V0ZWQgZW5lcmd5IGluZnJhc3RydWN0dXJlIGRlZXAgd2l0aGluIFVrcmFpbmUgd2hpY2ggY2F1c2VkIHBvd2VyIG91dGFnZXMsIHdpdGggVmlubnl0c2lhIGJlaW5nIG9uZSBvZiB0aGUgbW9zdCBhZmZlY3RlZCByZWdpb25zLgoKCgoKYGBge3J9CnVuaXF1ZShjb25mbGljdCRhZG1pbjEpCmBgYAoKYGBge3J9CmNlbnRyYWxfd2VzdGVybl91a3JhaW5lX3N0YXRlc19uYW1lIDwtICBjKCJWb2x5biIsICJSaXZuZSIsICJMdml2IiwgIlRlcm5vcGlsIiwgIktobWVsbnl0c2t5aSIsICJJdmFuby1GcmFua2l2c2siLCAiWmFrYXJwYXR0aWEiLCAiQ2hlcm5pdnRzaSIsICJWaW5ueXRzaWEiLCAiQ2hlcmthc3kiLCAiS2lyb3ZvZ3JhZCIsICJQb2x0YXZhIiApCmBgYAoKYGBge3J9Cgpjb25mbGljdF9jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdCAlPiUKICBkcGx5cjo6ZmlsdGVyKAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA+PSBhcy5EYXRlKCIyMDIyLTAyLTAxIikgJiBldmVudF9kYXRlIDw9IGFzLkRhdGUoIjIwMjMtMDEtMzEiKSwKICAgICAgICAgICAgICAgIHN1Yl9ldmVudF90eXBlID09ICJTaGVsbGluZy9hcnRpbGxlcnkvbWlzc2lsZSBhdHRhY2siLAogICAgICAgICAgICAgICAgYWRtaW4xICVpbiUgY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWUKICAgICAgICAgICAgICAgICkKYGBgCgpgYGB7cn0KbnVtYmVyX29mX2V2ZW50c19jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSA8LSBjb25mbGljdF9jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSAlPiUKICBncm91cF9ieShsYXRpdHVkZSwgbG9uZ2l0dWRlKSAlPiUKICBzdW1tYXJpemUobnVtYmVyX29mX2V2ZW50cyA9IG4oKSwgLmdyb3VwcyA9ICJkcm9wIikKYGBgCgpgYGB7cn0KY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmUgPC0gc3Vic2V0KHVrcmFpbmVfc3RhdGVzX3JkcywgTkFNRV8xICVpbiUgY2VudHJhbF91a3JhaW5lX3N0YXRlc19yZHNfbmFtZXMgfCBOQU1FXzEgJWluJSB3ZXN0ZXJuX3VrcmFpbmVfc3RhdGVzX3Jkc19uYW1lcykKY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfbWFwIDwtIGdncGxvdCgpICsKICBnZW9tX3BvbHlnb24oZGF0YT1jZW50cmFsX3dlc3Rlcm5fdWtyYWluZSwgIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCksIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuMiwgY29sb3I9ImJsYWNrIikgKyBndWlkZXMoZmlsbCA9ICJub25lIikgKyB0aGVtZV92b2lkKCkKY2VudHJhbF93ZXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyYWxfd2VzdGVybl91a3JhaW5lX21hcCArCiAgZ2VvbV9wb2ludChjb2xvcj0iYmxhY2siLCBzaGFwZT0yMSwgZmlsbD0iZGFya2JsdWUiLCBhbHBoYT0wLjYsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX2NlbnRyYWxfd2VzdGVybl91a3JhaW5lLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cykpICsKICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDEsIDEwKSwgZ3VpZGUgPSAnbGVnZW5kJywgYnJlYWtzID0gYygxLCAxMCwgMjAsIDUwKSwgbGFiZWxzID0gYygiMSIsICIxMCIsICIyMCIsICI1MCsiKSkgKwogIGxhYnMoc2l6ZSA9ICJOdW1iZXIgb2YgRXZlbnRzIikgKwogIGxhYnModGl0bGUgPSAiTG9uZy1SYW5nZSBTdHJpa2VzIGluIENlbnRyYWwgYW5kIFdlc3Rlcm4gVWtyYWluZSIsIGZvbnRmYWNlPSJib2xkIikgKyAKICBsYWJzKHN1YnRpdGxlID0gIkZlYnJ1YXJ5IDIwMjIgLSBKYW51YXJ5IDIwMjMgIikgKwogIGNvb3JkX21hcChwcm9qZWN0aW9uID0gImFsYmVycyIsIGxhdDAgPSA0OSwgbGF0MSA9IDU0KSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCgojIyBJbnRlcmFjdGl2ZSBNYXAKCmBgYHtyfQpsaWJyYXJ5KGxlYWZsZXQpCmBgYAoKYGBge3J9CnVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwIDwtIGxlYWZsZXQoKSAlPiUKICBhZGRUaWxlcygpICU+JQogIHNldFZpZXcobG5nID0gMzcuNzkzMywgbGF0ID0gNDguMTQ1MCwgem9vbSA9IDcpCnVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMgPSBsaXN0KCJEbmlwcm9wZXRyb3ZzayIsICJMdWhhbnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJaYXBvcml6aGlhIikKY29uZmxpY3RfZWFzdGVybl91a3JhaW5lIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBldmVudF9kYXRlID49IGFzLkRhdGUoIjIwMjItMDItMDEiKSAmIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMy0wMS0zMSIpLAogICAgICAgICAgICAgICAgZXZlbnRfdHlwZSAlaW4lIGMoIkV4cGxvc2lvbnMvUmVtb3RlIHZpb2xlbmNlIiwgIkJhdHRsZXMiLCAiVmlvbGVuY2UgYWdhaW5zdCBjaXZpbGlhbnMiKSwKICAgICAgICAgICAgICAgIGFkbWluMSAlaW4lIGVhc3Rlcm5fdWtyYWluZV9zdGF0ZXNfbmFtZXMpCmBgYAoKYGBge3J9CmV2ZW50cyA8LSBkYXRhLmZyYW1lKGxhdGl0dWRlID0gY29uZmxpY3RfZWFzdGVybl91a3JhaW5lJGxhdGl0dWRlLAogICAgICAgICAgICAgICAgICAgICBsb25naXR1ZGUgPSBjb25mbGljdF9lYXN0ZXJuX3VrcmFpbmUkbG9uZ2l0dWRlKQpgYGAKCmBgYHtyfQptIDwtIHVrcmFpbmVfaW50ZXJhY3RpdmVfbWFwICU+JQogIGFkZENpcmNsZU1hcmtlcnMoZGF0YSA9IGV2ZW50cywKICAgICAgICAgICAgICAgICAgIGxuZyA9IH5sb25naXR1ZGUsCiAgICAgICAgICAgICAgICAgICBsYXQgPSB+bGF0aXR1ZGUsCiAgICAgICAgICAgICAgICAgICByYWRpdXMgPSAxLAogICAgICAgICAgICAgICAgICAgY29sb3IgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgIGZpbGwgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjgpCgojIERpc3BsYXkgdGhlIG1hcAptCmBgYAoKYGBge3J9Cm0yIDwtIGFkZFBvbHlnb25zKAogIG1hcCA9IG0sCiAgZGF0YSA9IGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLAogIGZpbGxDb2xvciA9ICJvcmFuZ2UiLAogIGZpbGxPcGFjaXR5ID0gMC4yLAogIGNvbG9yID0gImJsYWNrIiwKICB3ZWlnaHQgPSAxCikKbTIKYGBgCgojIyBQcmUtSW52YXNpb24KClRoZSBFdXJvbWFpZGFuIHByb3Rlc3RzLCB3aGljaCBzdGFydGVkIGluIGxhdGUgMjAxMywgd2VyZSBwcmltYXJpbHkgY2VudGVyZWQgaW4gdGhlIGNhcGl0YWwgY2l0eSBvZiBLeWl2IChLaWV2KSBidXQgc3ByZWFkIHRvIG90aGVyIHJlZ2lvbnMgYXMgd2VsbC4gVGhlIHByb3Rlc3RzIGludm9sdmVkIGNsYXNoZXMgYmV0d2VlbiBkZW1vbnN0cmF0b3JzIGFuZCBsYXcgZW5mb3JjZW1lbnQsIHJlc3VsdGluZyBpbiBpbnN0YW5jZXMgb2YgdmlvbGVuY2UsIGluanVyaWVzLCBhbmQgZmF0YWxpdGllcy4KCkJlZm9yZSB0aGUgUnVzc2lhbiBpbnZhc2lvbiB0aGUgdmlvbGVuY2UgaW4gZWFzdGVybiBVa3JhaW5lIHdhcyBhbHJlYWR5IGNvbmNlbnRyYXRlZCBpbiBhcmVhcyBjbG9zZSB0byB0aGUgVWtyYWluaWFuLVJ1c3NpYW4gYm9yZGVyLCBwYXJ0aWN1bGFybHkgaW4gdGhlIERvbmV0c2sgYW5kIEx1aGFuc2sgcmVnaW9ucy4gQ2l0aWVzIHN1Y2ggYXMgRG9uZXRzaywgTHVoYW5zaywgTWFyaXVwb2wsIGFuZCBTbG92aWFuc2sgd2l0bmVzc2VkIGludGVuc2UgZmlnaHRpbmcgYW5kIGJlY2FtZSBob3RzcG90cyBvZiB2aW9sZW5jZS4KCkJvdGggc2lkZXMgb2YgdGhlIGNvbmZsaWN0IGVuZ2FnZWQgaW4gbWlsaXRhcnkgb3BlcmF0aW9ucywgaW5jbHVkaW5nIGFydGlsbGVyeSBzaGVsbGluZywgc25pcGVyIGF0dGFja3MsIGFuZCBhcm1lZCBjbGFzaGVzLiBUaGUgdmlvbGVuY2Ugd2FzIG5vdCBsaW1pdGVkIHRvIHNwZWNpZmljIGNpdGllcyBidXQgd2FzIHNwcmVhZCBhY3Jvc3MgdGhlIGNvbmZsaWN0LWFmZmVjdGVkIHJlZ2lvbnMuCgpUaGUgY29uZmxpY3QgcmVzdWx0ZWQgaW4gYSBzaWduaWZpY2FudCBudW1iZXIgb2YgY2l2aWxpYW4gY2FzdWFsdGllcyBhbmQgd2lkZXNwcmVhZCBkaXNwbGFjZW1lbnQgb2YgcmVzaWRlbnRzLiBDaXZpbGlhbnMsIGluY2x1ZGluZyB0aG9zZSBsaXZpbmcgaW4gdG93bnMgYW5kIHZpbGxhZ2VzIG5lYXIgdGhlIGZyb250IGxpbmVzLCBmYWNlZCB0aGUgcmlzayBvZiB2aW9sZW5jZSBhbmQgd2VyZSBvZnRlbiBjYXVnaHQgaW4gdGhlIGNyb3NzZmlyZS4KCmBgYHtyfQp1a3JhaW5lX21hcDIKYGBgCgpgYGB7cn0KY2VudHJvaWQgPC0gdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKHVrcmFpbmVfc3RhdGVzX3JkcykKdGV4dCA8LSBnZW9tX3RleHQoZGF0YSA9ICwgYWVzKHggPSBjZW50cm9pZFssIDFdLCB5ID0gY2VudHJvaWRbLCAyXSwgbGFiZWwgPSB1a3JhaW5lX3N0YXRlc19yZHMkTkFNRV8xKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkKYGBgCgpgYGB7cn0KcGlfdWtyYWluZV9tYXAgPC0gdWtyYWluZV9tYXAyICsgCiAgZ2VvbV90ZXh0KGFlcyh4ID0gY2VudHJvaWRbLCAxXSwgeSA9IGNlbnRyb2lkWywgMl0sIGxhYmVsID0gdWtyYWluZV9zdGF0ZXNfcmRzX25hbWVzKSwgc2l6ZT0yKSArIGxhYnModGl0bGUgPSAiUHJlLUludmFzaW9uIENvbmZsaWN0cyIsIGZvbnRmYWNlPSJib2xkIikgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSkgKyAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpCnBpX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNvbmZsaWN0X3BpX3VrcmFpbmUgPC0gY29uZmxpY3QgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgICAgICAgICAgICAgIGV2ZW50X2RhdGUgPD0gYXMuRGF0ZSgiMjAyMi0wMi0wMSIpLAogICAgICAgICAgICAgICAgIGNpdmlsaWFuX3RhcmdldGluZyAhPSAiIgogICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQpudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUgPC0gY29uZmxpY3RfcGlfdWtyYWluZSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CnBpX3VrcmFpbmVfbWFwICsKICBnZW9tX3BvaW50KGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBudW1iZXJfb2ZfZXZlbnRzX3BpX3VrcmFpbmUsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBmaWxsPWV2ZW50X3R5cGUpKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjEsIDEwKSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlZpb2xlbmNlIHRhcmdldGluZyBDaXZpbGlhbnMgaW4gUHJlLUludmFzaW9uIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJCZWZvcmUgRmVicnVhcnkgMjAyMiAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQpgYGAKCiMjIFBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUgUHJlLUludmFzaW9uCgpgYGB7cn0KY29uZmxpY3RfZWFzdGVybl91a3JhaW5lX3BpIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBkaXNvcmRlcl90eXBlID09ICJQb2xpdGljYWwgdmlvbGVuY2UiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA8IGFzLkRhdGUoIjIwMjItMDItMDEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgJWluJSBjKCJFeHBsb3Npb25zL1JlbW90ZSB2aW9sZW5jZSIsICJCYXR0bGVzIiwgIlZpb2xlbmNlIGFnYWluc3QgY2l2aWxpYW5zIiksCiAgICAgICAgICAgICAgICBhZG1pbjEgJWluJSBlYXN0ZXJuX3VrcmFpbmVfc3RhdGVzX25hbWVzKQpgYGAKCmBgYHtyfQpldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lX3BpIDwtIGNvbmZsaWN0X2Vhc3Rlcm5fdWtyYWluZV9waSAlPiUKICBncm91cF9ieShsb25naXR1ZGUsIGxhdGl0dWRlKSAlPiUKICByZWZyYW1lKG51bWJlcl9vZl9ldmVudHMgPSBuKCksIGV2ZW50X3R5cGUpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgPC0gZ2dwbG90KCkgKwogIGdlb21fcG9seWdvbihkYXRhPWVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzLCAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwgZmlsbD0ib3JhbmdlIiwgYWxwaGE9MC4yLCBjb2xvcj0iYmxhY2siKSArIGd1aWRlcyhmaWxsID0gIm5vbmUiKSArIHRoZW1lX3ZvaWQoKQplYXN0ZXJuX3VrcmFpbmVfbWFwCmBgYAoKYGBge3J9CmNlbnRyb2lkIDwtIGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzJGNlbnRyb2lkIDwtIGNvb3JkaW5hdGVzKGVhc3RfdWtyYWluZV9zdGF0ZXNfcmRzKQpjZW50cm9pZFsyXSA9IGNlbnRyb2lkWzJdKzAuNApjZW50cm9pZFs3XSA9IGNlbnRyb2lkWzddLTAuNApjZW50cm9pZFszXSA9IGNlbnRyb2lkWzNdLTAuNAp0ZXh0IDwtIGdlb21fdGV4dChkYXRhID0gLCBhZXMoeCA9IGNlbnRyb2lkWywgMV0sIHkgPSBjZW50cm9pZFssIDJdLCBsYWJlbCA9IGMoIkRuaXByb3BldHJvdnNrIiwgIkRvbmV0c2siLCAiS2hhcmtpdiIsICJMdWhhbnNrIiwgIlphcG9yaXpoaWEiKSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDQpCmBgYAoKYGBge3J9CmVhc3Rlcm5fdWtyYWluZV9tYXAgKwogIGdlb21fcG9pbnQoZGF0YSA9IGV2ZW50X2NvdW50c19lYXN0ZXJuX3VrcmFpbmVfcGksIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSBudW1iZXJfb2ZfZXZlbnRzLCBjb2xvcj1ldmVudF90eXBlKSkgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGRhdGEgPSBldmVudF9jb3VudHNfZWFzdGVybl91a3JhaW5lX3BpLCBhZXMoeCA9IGxvbmdpdHVkZSwgeSA9IGxhdGl0dWRlLCBzaXplID0gbnVtYmVyX29mX2V2ZW50cywgZmlsbD1ldmVudF90eXBlKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhyYW5nZSA9IGMoMC4xLCA1KSkgKwogIGxhYnMoY29sb3IgPSAiRXZlbnQgVHlwZSIsIHNpemUgPSAiTnVtYmVyIG9mIEV2ZW50cyIpICsKICBsYWJzKHRpdGxlID0gIlBvbGl0aWNhbCBWaW9sZW5jZSBpbiBFYXN0ZXJuIFVrcmFpbmUgUHJlLUludmFzaW9uIiwgZm9udGZhY2U9ImJvbGQiKSArIAogIGxhYnMoc3VidGl0bGUgPSAiRmVicnVhcnkgMjAyMiAtIEphbnVhcnkgMjAyMyAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlPSJib2xkIiksIHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgdGV4dApgYGAKCmBgYHtyfQpjb25mbGljdF91a3JhaW5lX3BpX3Jpb3RzIDwtIGNvbmZsaWN0ICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICAgICAgICAgICAgICBkaXNvcmRlcl90eXBlID09ICJQb2xpdGljYWwgdmlvbGVuY2UiLAogICAgICAgICAgICAgICAgZXZlbnRfZGF0ZSA8IGFzLkRhdGUoIjIwMjItMDItMDEiKSwKICAgICAgICAgICAgICAgIGV2ZW50X3R5cGUgPT0gIlJpb3RzIgogICAgICAgICAgICAgICAgKQpgYGAKCmBgYHtyfQp1a3JhaW5lX21hcDIgKwogIGdlb21fcG9pbnQoY29sb3I9ImJsYWNrIiwgc2hhcGU9MjEsIGZpbGw9Im9yYW5nZSIsIGFscGhhPTAuNiwgZGF0YSA9IGNvbmZsaWN0X3VrcmFpbmVfcGlfcmlvdHMsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsIHNpemUgPSAxKSkgKwogIGxhYnModGl0bGUgPSAiUmlvdHMgaW4gUHJlLUludmFzaW9uIFVrcmFpbmUiLCBmb250ZmFjZT0iYm9sZCIpICsgCiAgbGFicyhzdWJ0aXRsZSA9ICJCZWZvcmUgRmVicnVhcnkgMjAyMiAiKSArCiAgY29vcmRfbWFwKHByb2plY3Rpb24gPSAiYWxiZXJzIiwgbGF0MCA9IDQ5LCBsYXQxID0gNTQpICsKICBndWlkZXMoc2l6ZSA9ICJub25lIikgKwogIHRoZW1lX3ZvaWQoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZT0iYm9sZCIpLCBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKYGBgCg==